Skip to content

Build report, console modes, and warning control - #12572

Closed
gnodet wants to merge 10 commits into
masterfrom
feature/12571-build-report
Closed

Build report, console modes, and warning control#12572
gnodet wants to merge 10 commits into
masterfrom
feature/12571-build-report

Conversation

@gnodet

@gnodet gnodet commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

This PR has been superseded. The work has been split into 5 smaller, independently reviewable PRs that form a dependency chain. Each builds on the previous one.

PR Chain

# PR Title Base
1 #12694 Logging foundation: structured LogEvent, JUL handler, Log API enhancements master
2 #12695 Build report: structured JSON report with per-mojo log capture feature/logging-foundation
3 #12697 Console modes: --console=plain/rich/verbose/machine feature/build-report
4 #12698 Warning mode, diagnostic collector, BuilderProblem enrichments feature/console-modes
5 #12699 mvnlog: build log viewer, integration tests, script routing feature/warning-mode

Follow-up: #12647 — Pipe structured BuilderProblems into DiagnosticCollector (targets feature/warning-mode)

Review starts at PR 1 and proceeds through the chain. Each PR compiles and passes tests independently.


The rest of this description is kept as a high-level overview of the full feature set across all 5 PRs.


Build Report Foundation

What users see

--console=plain — compact CI output (default when CI=true)

One line per completed module, no ANSI, no status bar. Auto-selected on CI (CI=true, JENKINS_URL, etc.):

$ mvn validate --console=plain
[INFO] Apache Maven [1/38] ................................ SUCCESS [  0.539 s]
[INFO] Maven 4 API [2/38] ................................. SUCCESS [  0.017 s]
[INFO] Maven 4 API :: Meta annotations [3/38] ............. SUCCESS [  0.019 s]
[INFO] Maven 4 API :: Dependency Injection [4/38] ......... SUCCESS [  0.018 s]
[INFO] Maven 4 API :: XML [5/38] .......................... SUCCESS [  0.027 s]
[INFO] Maven 4 API :: Model [6/38] ........................ SUCCESS [  0.070 s]
...
[INFO] Maven 4 CLI [35/38] ................................ SUCCESS [  0.240 s]
[INFO] Maven Plugin Testing Mechanism [36/38] ............. SUCCESS [  0.162 s]
[INFO] Maven Embedder (deprecated) [37/38] ................ SUCCESS [  0.178 s]
[INFO] Apache Maven Distribution [38/38] .................. SUCCESS [  0.514 s]
[INFO]
[INFO] BUILD SUCCESS
[INFO] 38 modules | 38 passed
[INFO] Total time:  5.519 s
[INFO] Full report: target/build-reports/build-report-latest.json

--console=rich — live status bar (default on interactive TTY)

During the build, the bottom of the terminal shows a live JLine status area that updates in place. All plugin INFO/WARN output is suppressed — only ERRORs scroll above the status bar:

 Maven 4.1.0-SNAPSHOT ─ building Apache Maven 4.1.0-SNAPSHOT
 ● maven-core  maven-compiler-plugin:compile  8s
 ● maven-api-core  maven-surefire-plugin:test  3s
────────────────────────────────────────────────────────────────────
 ✓ ✓ ✓ ● ● ○ ○ ○ ○ ○ [5/10]  32s  ↓ core-4.1.0.jar 256KB/512KB

With large reactors (where per-module indicators don't fit), the separator becomes a proportional progress bar:

 Maven 4.1.0-SNAPSHOT ─ building Apache Camel 4.22.0-SNAPSHOT
 ● camel-jaxb  flatten-maven-plugin:flatten  0s
 ● camel-core  maven-compiler-plugin:compile  8s
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━────────────────────────────────────── [77/673]  1m 18s

At the end, the status bar is torn down and replaced with a compact summary:

BUILD SUCCESS
38 modules | 38 passed
Total time:  5.772 s
Full report: target/build-reports/build-report-latest.json

When diagnostics are present:

BUILD SUCCESS
38 modules | 38 passed
Diagnostics: 3 warnings — run mvnlog to see details
Total time:  32.1s
Full report: target/build-reports/build-report-latest.json

--console=machine — JSON lines for tools and LLM agents

One JSON object per line, designed for piping to jq, IDE integrations, and AI agents:

$ mvn validate --console=machine
{"event":"build.started","timestamp":"...","projectCount":38,"goals":"validate","profiles":"signing-key"}
{"event":"module.started","timestamp":"...","module":"Apache Maven","groupId":"org.apache.maven","artifactId":"maven","version":"4.1.0-SNAPSHOT","index":1,"total":38}
{"event":"mojo.started","timestamp":"...","module":"Apache Maven","plugin":"maven-enforcer-plugin","goal":"enforce","phase":"validate","executionId":"enforce-bytecode-version"}
{"event":"log","timestamp":"...","level":"INFO","module":"maven","logger":"...","message":"Rule 0: org.apache.maven.enforcer.rules.version.RequireJavaVersion passed"}
{"event":"mojo.succeeded","timestamp":"...","module":"Apache Maven","plugin":"maven-enforcer-plugin","goal":"enforce","duration":0.33}
{"event":"module.succeeded","timestamp":"...","module":"Apache Maven","duration":0.543}
...
{"event":"build.finished","timestamp":"...","status":"SUCCESS","duration":4.363,"total":38,"passed":38,"failed":0,"skipped":0}

--console=verbose — full output (Maven 4.0 default)

Unchanged from today's Maven 4.0 behavior — all per-mojo banners, plugin output, download progress.

--console=auto (the default)

Selects automatically: CI=true or JENKINS_URL set → plain; interactive TTY → rich; otherwise → verbose.

Warning summary at end of build

All console modes show a deduplicated warning summary at end of build (unless --warning-mode=none).

--warning-mode controls behavior:

Mode During build End of build Exit code
all (default) show warnings show summary 0
summary suppress inline show summary 0
none suppress all suppress all 0
fail show warnings show summary 1 (if any warning)

Version info on failure

When the build fails, Maven and Java version are printed to help with bug reports.

Structured build report JSON

Every build writes target/build-reports/build-report-latest.json with per-module, per-mojo execution data, log output, and diagnostics.

mvnlog — build report viewer

After a build completes, mvnlog reads the report JSON and renders a human-readable view:

$ mvnlog                    # view latest build report
$ mvnlog warnings           # just the deduplicated warnings
$ mvnlog module core        # output from a specific module
$ mvnlog --json             # raw JSON output for tools

How it works

Console mode architecture

Each console mode is a pair of cooperating classes:

Mode BuildEventListener ExecutionListener
rich RichBuildEventListener (JLine status bar) RichExecutionEventLogger (suppress per-mojo banners)
plain PlainBuildEventListener (no-op status) PlainExecutionEventLogger (one line per module)
machine MachineBuildEventListener (JSON log/transfer events) MachineExecutionEventLogger (JSON lifecycle events)
verbose existing SimpleBuildEventListener existing ExecutionEventLogger

Build report pipeline

  1. BuildReportCollector — injected ExecutionListener that captures every lifecycle event, mojo execution, and log message into an in-memory report
  2. BuildReportWriter — writes the report to target/build-reports/build-report-latest.json at session end
  3. BuilderProblem — universal diagnostic currency: model validation warnings, plugin validation, and (with PR Fix #12643: Pipe structured BuilderProblems into DiagnosticCollector #12647) plugin-reported diagnostics all flow through BuilderProblem into DiagnosticCollector

DiagnosticReporter (PR #12647)

A new Maven 4 API service that plugins can inject to report structured diagnostics:

@gnodet gnodet changed the title Fix #12571: Add structured build report (Phase 0) Fix #12571: Build output overhaul — structured report, console modes, warning control Jul 29, 2026
@gnodet gnodet changed the title Fix #12571: Build output overhaul — structured report, console modes, warning control Fix #12571: Build Report Foundation — structured report, console modes, warning control Jul 29, 2026
@gnodet
gnodet force-pushed the feature/12571-build-report branch 6 times, most recently from 3192bb4 to 87be78e Compare July 29, 2026 14:59
@gnodet gnodet changed the title Fix #12571: Build Report Foundation — structured report, console modes, warning control Build Report Foundation — structured report, console modes, warning control Jul 29, 2026
@gnodet gnodet added this to the 4.1.0 milestone Jul 30, 2026
…s, warning control

Add a comprehensive build reporting infrastructure to Maven 4.1.0:

**Structured Build Report** (Phase 0-1)
- BuildReport API in maven-api-core with ModuleReport, MojoReport,
  FailureReport, and LogEvent data model
- BuildReportCollector EventSpy that captures lifecycle events,
  per-mojo log output, and build diagnostics
- JSON writer producing timestamped build-report-*.json files
- Deduplicated warning summary printed at end of build

**Console Modes** (Phase 2-4)
- ConsoleMode enum (AUTO/PLAIN/RICH/MACHINE) with --console CLI flag
- PlainBuildEventListener for compact CI output
- RichBuildEventListener with JLine status bar for interactive terminals
- MachineBuildEventListener for JSON-lines structured output

**Warning Control** (Phase 5)
- --warning-mode CLI flag (ALL/SUMMARY/NONE)
- Log.warn() interception for automatic Maven 3 plugin coverage
- -Dmaven.diagnostic.suppress=key for selective suppression

**Build Log Viewer** (mvnlog)
- mvnlog CLI tool for post-build report inspection
- --json flag for raw JSON output
- Shell scripts for Unix and Windows

**Plugin API** (DiagnosticReporter)
- BuilderProblem.builder() static factory with fluent Builder API
- DiagnosticReporter Service interface for Maven 4 plugins
- DefaultDiagnosticReporter implementation with auto-discovery

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@gnodet
gnodet force-pushed the feature/12571-build-report branch from d7bb105 to 63da8ce Compare July 31, 2026 11:57
gnodet added a commit that referenced this pull request Aug 4, 2026
Port and modernize the incremental build context from PR #1118,
building on the original Sonatype plexus-build-api / Takari
incrementalbuild work.

API (maven-api-core):
- BuildContext: register inputs, check status, associate
  outputs, skip execution, automatic stale output cleanup
- SPI: Workspace (NORMAL/ESCALATED/SUPPRESSED),
  CommittableBuildContext, BuildContextEnvironment,
  BuildContextFinalizer
- Diagnostic messages are NOT part of this API — use
  DiagnosticReporter from the build report API instead

Implementation (maven-impl):
- DefaultBuildContext with timestamp/size change detection
- State serialization for cross-build persistence
- PathMatcherFactory integration for Ant-style patterns
- 36 tests

Maven integration (maven-core):
- MojoExecutionScoped DI wiring
- ClasspathDigester + MojoConfigurationDigester for automatic
  configuration change detection
- MavenBuildContextFinalizer for post-mojo commit
- maven.buildcontext.skip property to disable entirely
- Performance: released-artifact digest bypass, no-op state skip,
  single-syscall file status, field reflection cache

Based on #12572 (Build Report Foundation).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When the reactor has more modules than fit as individual ✓/●/○
indicators on the terminal width, switch to a full-width proportional
progress bar: green ━ for completed, yellow ━ for active, dim ─ for
remaining, with the counter and elapsed time appended.

The progress bar replaces the separator line — one line instead of
two (no redundant horizontal rule above the bar). This also gives
an extra project slot line to the status area.

Small reactors (≤ maxIndicators) keep the per-module indicators
with the separate separator line, where each module gets its own
symbol.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@gnodet
gnodet force-pushed the feature/12571-build-report branch from 83ce6ac to 6fd5983 Compare August 4, 2026 22:33
@gnodet gnodet changed the title Build Report Foundation — structured report, console modes, warning control Build report, console modes, and warning control Aug 6, 2026
gnodet and others added 7 commits August 7, 2026 08:11
…ollector

Route structured validation problems from 4 pathways (settings, toolchains,
model validation, graph building) into DefaultDiagnosticCollector so they
appear in the build report with full key/suggestion/documentationUrl metadata
instead of being re-logged as plain text.

Pathways:
- LookupInvoker: settings validation problems
- MavenInvoker: toolchains validation problems
- DefaultProjectsSelector: model validation problems (ModelProblem → BuilderProblem)
- DefaultMaven: graph building problems (ModelProblem → BuilderProblem)

Also adds EXCLUDED_LOGGERS in BuildReportCollector to prevent double-counting
when the same problems are both piped structurally and logged via SLF4J.

Migrates all test files from DefaultBuilderProblem constructor to
BuilderProblem.builder() API.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Change the PluginValidationManager interface from String-based to
BuilderProblem-based, enabling structured problem reporting with keys,
severity, and suggestions throughout the plugin validation pipeline.

- Change 3 abstract report methods from String issue to BuilderProblem
- Add deprecated String-based default methods for backward compat
- Update all 9 call sites (7 validators + 1 plugin manager) to create
  BuilderProblem with structured key, severity, and suggestion
- Inject DefaultDiagnosticCollector into DefaultPluginValidationManager
  to pipe problems into the diagnostic pipeline
- Add japicmp exclusion for the intentional API break
- Add DefaultPluginValidationManager to EXCLUDED_LOGGERS in
  BuildReportCollector to prevent double-counting

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Injector.bindFactory(Class, Function<Key, T>): factory-based binding
  that receives the full injection-point Key (including @nAmed qualifier),
  enabling qualifier-derived instances like hierarchical logger names.

- Log.child(String): returns a child logger with hierarchical naming
  (e.g. "compiler:compile" → "compiler:compile.diagnostics"), useful
  when plugins delegate to sub-components that need independently
  filterable log output.

- Log.problem(BuilderProblem): reports a structured problem to the
  diagnostic collector with dedup key, suggestion, and documentation
  URL, while also logging at the appropriate level. Uses a thread-local
  flag to prevent double-counting by BuildReportCollector's WARN
  auto-promotion.

- DefaultMavenPluginManager: switched from bindInstance to bindFactory
  for Log injection, so @Inject @nAmed("diagnostics") Log in a
  DI-managed plugin component gets "compiler:compile.diagnostics".

- Fixed pre-existing bug: DefaultLog.warn(Supplier, Throwable) was
  calling logger.info() instead of logger.warn().

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
… bindFactory()

Keep only Log.child(String) — a clean, backward-compatible default method
that lets sub-components log under an independently filterable name
(e.g. "compiler:compile" → "compiler:compile.diagnostics").

Removed from the earlier commit:
- Log.problem(BuilderProblem) — conflated logging with problem reporting;
  plugins should use DiagnosticReporter directly instead.
- Injector.bindFactory() — too much DI machinery for a single use case;
  plugins can call logger.child() at the call site.
- STRUCTURED_PROBLEM_ACTIVE ThreadLocal — fragile invisible coupling
  between DefaultLog and BuildReportCollector.
- Factory-based Log binding in DefaultMavenPluginManager.

Also fixes pre-existing bug: DefaultLog.warn(Supplier, Throwable) was
calling logger.info() instead of logger.warn().

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
LogEvent now carries projectId() and mojoId() so every log message
(including JUL-bridged ones) is self-describing. The mojo ID is set
in MDC by LoggingExecutionListener on mojo start/finish, read by
ProjectBuildLogAppender, and embedded in the event. Machine mode
emits the mojoId in its JSON output.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
DefaultLog now uses the mojo implementation class name as its SLF4J
logger name instead of getFullGoalName(). This makes Log and JUL
produce identical SLF4J loggers when plugins use the conventional
class-name pattern, and enables hierarchical SLF4J level configuration
(e.g. org.apache.maven.plugin.compiler=DEBUG).

The mojoId format changes from goal@executionId to
prefix:goal@executionId (e.g. compiler:compile@default-compile)
for unambiguous identification.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Debug is currently overloaded: user-relevant diagnostic messages
(e.g. "recompiling because annotation processor changed") share the
same level as Maven internal details (resolver negotiation, model
interpolation). This makes -X output unusable for users investigating
their build.

Add trace() methods to the Maven 4 Log API, mirroring the existing
debug/info/warn/error pattern. Trace maps to SLF4J TRACE and JUL
FINEST. The intent is that Maven internals demote to trace, leaving
debug for user-facing diagnostic information.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
desruisseaux
desruisseaux previously approved these changes Aug 7, 2026
@gnodet

gnodet commented Aug 7, 2026

Copy link
Copy Markdown
Contributor Author

Closing — this monolith PR has been fully superseded by the 5-PR chain:

  1. Logging foundation: structured LogEvent, JUL handler, Log API enhancements #12694 — Logging foundation
  2. Build report: structured JSON report with per-mojo log capture #12695 — Build report
  3. Console modes: --console=plain/rich/verbose/machine #12697 — Console modes
  4. Warning mode, diagnostic collector, BuilderProblem enrichments #12698 — Warning mode + diagnostics
  5. mvnlog: build log viewer, integration tests, script routing #12699 — mvnlog viewer

Plus #12647 — Structured BuilderProblems pipeline

Review starts at PR #12694.

@gnodet gnodet closed this Aug 7, 2026
@github-actions github-actions Bot removed this from the 4.1.0 milestone Aug 7, 2026
gnodet added a commit that referenced this pull request Aug 8, 2026
Add a structured build report that captures per-module and per-mojo
execution results, timing, log events, and failures as a JSON file
(target/build-reports/) at the end of every build.

Part 2 of the #12572 split. Builds on the logging foundation from
PR #12694 (LogEvent, LogLevel, LogEventSink).

New API interfaces:
- BuildReport: root report with metadata, modules, failures, problems
- BuildStatus: SUCCESS/FAILURE/SKIPPED enum
- ModuleReport: per-module results with mojo list
- MojoReport: per-mojo execution with captured log events
- FailureReport: exception details and stack traces

Implementation:
- BuildReportCollector: EventSpy that tracks lifecycle events and
  captures log output via LogEventSink, routing events to
  mojo/module/build-level buffers using thread-based tracking
- BuildReportJsonWriter: zero-dependency JSON serializer
- Atomic file writes with timestamped files and latest symlink
- Thread-safe for parallel builds (-T)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
gnodet added a commit that referenced this pull request Aug 8, 2026
Add the --console CLI flag with four output modes:
- plain: compact one-line-per-module output for CI
- rich: JLine status bar with live reactor progress
- verbose: full mojo-level output (current default)
- machine: JSON lines for piping to external tools

Part 3 of the #12572 split (depends on build report PR #12695).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
gnodet added a commit that referenced this pull request Aug 8, 2026
Add --warning-mode CLI flag (summary/all/none/fail) for controlling
how build warnings are displayed. Enrich BuilderProblem with key,
suggestion, documentationUrl, INFO severity, and a builder API.
Add DiagnosticReporter service and DefaultDiagnosticCollector for
deduplication across parallel module builds.

Part 4 of the #12572 split (depends on console modes PR #12697).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
gnodet added a commit that referenced this pull request Aug 8, 2026
Add the mvnlog tool for viewing and analyzing build-report JSON files.
Includes BuildReportRenderer for human-readable output, SimpleJsonReader
for dependency-free JSON parsing, shell scripts (mvnlog/mvnlog.cmd),
and --log routing in mvn/mvn.cmd. Also adds integration tests for
build report generation, console modes, and the mvnlog viewer, plus
--console=verbose flags for ITs that depend on verbose output.

Part 5 of the #12572 split (depends on warning mode PR #12698).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
gnodet added a commit that referenced this pull request Aug 8, 2026
Add the mvnlog tool for viewing and analyzing build-report JSON files.
Includes BuildReportRenderer for human-readable output, SimpleJsonReader
for dependency-free JSON parsing, shell scripts (mvnlog/mvnlog.cmd),
and --log routing in mvn/mvn.cmd. Also adds integration tests for
build report generation, console modes, and the mvnlog viewer, plus
--console=verbose flags for ITs that depend on verbose output.

Part 5 of the #12572 split (depends on warning mode PR #12698).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants